package cn.rwklyd.BookKeeping.service;

import cn.rwklyd.BookKeeping.util.EmailUtils;
import cn.rwklyd.BookKeeping.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@Service
@Slf4j
public class VerificationCodeService {

    private static final String EMAIL_CODE_PREFIX = "email:code:";
    private static final String EMAIL_BINDING_PREFIX = "email:binding:";
    private static final long CODE_EXPIRE_MINUTES = 5;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private RedisUtils redisUtils;
    
    @Autowired
    private AsyncEmailService asyncEmailService;

    /**
     * 发送验证码
     * @param email 邮箱
     * @param type 类型（register/reset等）
     * @return 是否发送成功
     */
    @PreAuthorize("permitAll()")    // 允许匿名访问
    public boolean sendCode(String email, String type) {
        log.info("开始生成验证码，邮箱: {}, 类型: {}", email, type);
        // 生成验证码
        String code = emailUtils.generateVerificationCode();

        // 存储到Redis，键格式: email:code:类型:邮箱
        String key = EMAIL_CODE_PREFIX + type + ":" + email;
        redisUtils.set(key, code, CODE_EXPIRE_MINUTES, TimeUnit.MINUTES);
        log.info("验证码已存储到Redis，键: {}", key);

        try {
            // 构建邮件内容
            String subject = "个人记账本 - 验证码";
            String content = "<div style='background-color:#f7f7f7;padding:20px;'>" +
                    "<div style='background-color:#ffffff;padding:20px;border-radius:5px;'>" +
                    "<h2 style='color:#07C160;'>个人记账本</h2>" +
                    "<p>您好，您正在注册个人记账本账号，验证码为：</p>" +
                    "<div style='background-color:#07C160;color:#ffffff;font-size:24px;padding:10px;text-align:center;border-radius:5px;letter-spacing:5px;'>" +
                    code +
                    "</div>" +
                    "<p style='margin-top:20px;font-size:12px;color:#999;'>验证码有效期为5分钟，请勿泄露给他人。</p>" +
                    "</div></div>";
            
            // 使用异步服务发送邮件
            log.info("开始异步发送邮件");
            CompletableFuture<Boolean> future = asyncEmailService.sendEmailAsync(email, subject, content);
            
            // 等待结果，但设置超时时间
            boolean result = future.get(10, TimeUnit.SECONDS);
            log.info("邮件发送结果: {}", result);
            return result;
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            log.error("发送验证码邮件异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 验证验证码
     * @param email 邮箱
     * @param code 验证码
     * @param type 类型
     * @return 是否验证成功
     */
    public boolean verifyCode(String email, String code, String type) {
        // 获取Redis中的验证码
        String key = EMAIL_CODE_PREFIX + type + ":" + email;
        String savedCode = redisUtils.get(key);

        // 验证码不存在或不匹配
        if (savedCode == null || !savedCode.equals(code)) {
            return false;
        }

        // 验证成功后删除验证码，防止重复使用
        redisUtils.delete(key);

        // 创建邮箱绑定记录，用于后续验证
        String bindingKey = EMAIL_BINDING_PREFIX + type + ":" + email;
        redisUtils.set(bindingKey, code, 30, TimeUnit.MINUTES); // 绑定有效期30分钟

        return true;
    }

    /**
     * 检查邮箱是否已通过验证
     * @param email 邮箱
     * @param code 验证码
     * @param type 类型
     * @return 是否已通过验证
     */
    public boolean checkEmailVerified(String email, String code, String type) {
        String bindingKey = EMAIL_BINDING_PREFIX + type + ":" + email;
        String savedCode = redisUtils.get(bindingKey);

        // 验证码存在且匹配
        return savedCode != null && savedCode.equals(code);
    }

    /**
     * 清除邮箱验证状态
     * @param email 邮箱
     * @param type 类型
     */
    public void clearEmailVerification(String email, String type) {
        String bindingKey = EMAIL_BINDING_PREFIX + type + ":" + email;
        redisUtils.delete(bindingKey);
    }
}